package dataloader

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	// "mall/service/blog/rpc/blogclient"
	"mall/service/wpgql/api/internal/graph/model"
	"mall/service/wpgql/api/internal/graph/storage"
	"mall/service/wpgql/api/internal/svc"

	"github.com/graph-gophers/dataloader"
	gopher_dataloader "github.com/graph-gophers/dataloader"
)

// GetCategory wraps the Category dataloader for efficient retrieval by category ID
func GetCategory(ctx context.Context, categoryID string) (*model.Category, error) {
	loaders := For(ctx)
	if loaders == nil {
		return nil, nil
	}

	thunk := loaders.categoryLoader.Load(ctx, gopher_dataloader.StringKey(categoryID))
	result, err := thunk()
	if err != nil {
		return nil, err
	}

	output, ok := result.(*model.Category)
	if !ok {
		return nil, nil
	}

	return output, nil
}

type CategoryBatcher struct {
	storage storage.Storage
	svcCtx  *svc.ServiceContext
}

func NewCategoryBatcher(svcCtx *svc.ServiceContext) *CategoryBatcher {
	return &CategoryBatcher{
		storage: svcCtx.Storage,
		svcCtx:  svcCtx,
	}
}

func (b *CategoryBatcher) get(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
	fmt.Printf("dataloader.CategoryBatcher.get, categories: [%s]\n", strings.Join(keys.Keys(), ","))
	// create a map for remembering the order of keys passed in
	keyOrder := make(map[string]int, len(keys))
	// collect the keys to search for
	var dbIDs []string
	for idx, key := range keys {
		dbIDs = append(dbIDs, key.String())
		keyOrder[key.String()] = idx
	}

	// search for those categories
	dbRecords, err := b.storage.GetCategories(ctx, dbIDs)
	// if DB error, return
	if err != nil {
		return []*dataloader.Result{{Data: nil, Error: err}}
	}

	// construct an output array of dataloader results
	results := make([]*dataloader.Result, len(keys))
	// enumerate records, put into output
	for _, record := range dbRecords {
		if record.DatabaseID > 0 { // 缓存有记录，数据库有记录
			idx, ok := keyOrder[record.ID]
			// if found, remove from index lookup map so we know elements were found
			if ok {
				results[idx] = &dataloader.Result{Data: record, Error: nil}
				delete(keyOrder, record.ID)
			}
		} else { // 缓存有记录，数据库无记录
			idx, ok := keyOrder[record.ID]
			if ok {
				e := fmt.Errorf("category not found %s", record.ID)
				results[idx] = &dataloader.Result{Data: nil, Error: e}
				delete(keyOrder, record.ID)
			}
		}
	}

	var ids []int64 // 缓存无记录
	for dbID, _ := range keyOrder {
		if i, err := strconv.ParseInt(dbID, 10, 64); err == nil {
			ids = append(ids, i)
		}
	}
	if len(ids) > 0 {
		// res, err := b.svcCtx.BlogRpc.CategoryList(ctx, &blogclient.CategoryListRequest{
		// 	IdIn: ids,
		// })
		// if err != nil || len(res.Data) == 0 { // 查询失败或无数据，向缓存填充空数据，防止反复查询
		// 	for dbID, idx := range keyOrder {
		// 		er := b.storage.PutCategory(ctx, &model.Category{
		// 			DatabaseID: 0,
		// 			ID:         dbID,
		// 		})
		// 		if er != nil {
		// 			results[idx] = &dataloader.Result{Data: nil, Error: er}
		// 		} else {
		// 			results[idx] = &dataloader.Result{Data: nil, Error: err}
		// 		}
		// 		delete(keyOrder, dbID)
		// 	}
		// } else {
		// 	for _, category := range res.Data {
		// 		var id string
		// 		id = model.EncodeID("category", category.Id, b.svcCtx.Config.Query.CursorSplitter)
		// 		var parentId string
		// 		if category.ParentID > 0 {
		// 			parentId = model.EncodeID("category", category.ParentID, b.svcCtx.Config.Query.CursorSplitter)
		// 		}
		// 		var (
		// 			count            int = int(category.Count)
		// 			parentDatabaseID int = int(category.ParentID)
		// 			termGroupID      int = int(category.TermGroupID)
		// 			termTaxonomyID   int = int(category.TermTaxonomyID)
		// 		)
		// 		record := &model.Category{
		// 			Count:            &count,
		// 			DatabaseID:       int(category.Id),
		// 			Description:      &category.Description,
		// 			ID:               id,
		// 			IsContentNode:    category.IsContentNode,
		// 			IsRestricted:     &category.IsRestricted,
		// 			IsTermNode:       category.IsTermNode,
		// 			Link:             &category.Link,
		// 			Name:             &category.Name,
		// 			ParentDatabaseID: &parentDatabaseID,
		// 			ParentID:         &parentId,
		// 			Slug:             &category.Slug,
		// 			TaxonomyName:     &category.TaxonomyName,
		// 			TermGroupID:      &termGroupID,
		// 			TermTaxonomyID:   &termTaxonomyID,
		// 			URI:              &category.URI,
		// 		}
		// 		b.storage.PutCategory(ctx, record)

		// 		idx, ok := keyOrder[id]
		// 		// if found, remove from index lookup map so we know elements were found
		// 		if ok {
		// 			results[idx] = &dataloader.Result{Data: record, Error: nil}
		// 			delete(keyOrder, id)
		// 		}
		// 	}
		// }
	}

	// fill array positions with errors where not found in DB
	for dbID, idx := range keyOrder {
		err := fmt.Errorf("category not found %s", dbID)
		results[idx] = &dataloader.Result{Data: nil, Error: err}
	}

	// return results
	return results
}
